/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ee.ioc.phon.ohos.speechutils.view;

import ee.ioc.phon.ohos.speechutils.ResourceTable;
import ee.ioc.phon.ohos.speechutils.utils.LogUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

import java.io.IOException;
import java.io.InputStream;

/**
 * 话筒
 *
 * @since 2021-03-20
 */
public class MicButton extends Component implements Component.EstimateSizeListener, Component.DrawTask {
    /**
     * more线条颜色
     */
    public static final int COLOR_INDICATOR_DEFAULT = 0xff3F51B5;
    /**
     * COLOR_INDICATOR_GONE
     */
    public static final int COLOR_INDICATOR_GONE = 0x00000000;
    private static final int ROTATION_SPEED = 1;
    /**
     * ER
     */
    private static final int ER = 2;
    /**
     * RGB
     */
    private static final int RGB = 0xff0000;
    /**
     * RGB2
     */
    private static final int RGB2 = 0x00ff00;
    /**
     * RGB3
     */
    private static final int RGB3 = 0x0000ff;
    /**
     * 2f
     */
    private static final float ERF = 2f;
    /**
     * 1f
     */
    private static final float YIF = 1f;
    /**
     * 0.45
     */
    private static final float NUM_045 = 0.45f;
    /**
     * 0.55f
     */
    private static final float NUM_055 = 0.55f;
    /**
     * 0.01f
     */
    private static final float NUM_001 = 0.01f;
    private static final String MICBUTTONTAG = "MICTAG";
    private static final float NUM_20 = 20f;
    private float rmsdbLevel = 0;
    private PixelMapHolder pixelMapHolder;
    private RectFloat rectSrc;

    private int width = 0;
    private int height = 0;
    private int min = 0;
    private int imageSize;
    private Paint backgroundPaint;
    private Paint wavePaint;

    /**
     * 构造参数
     *
     * @param context 上下文
     */
    public MicButton(Context context) {
        super(context);
        init();
    }

    /**
     * 构造参数
     *
     * @param context 上下文
     * @param attrs 属性参数
     */
    public MicButton(Context context, AttrSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 构造参数
     *
     * @param context 上下文
     * @param attrs 属性参数
     * @param defStyleAttr 属性样式
     */
    public MicButton(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 测量方法onMeasure相似
     *
     * @param widthMeasureSpec widthMeasureSpec
     * @param heightMeasureSpec heightMeasureSpec
     * @return boolean isOnEstimateSize
     */
    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        width = EstimateSpec.getSize(widthMeasureSpec);
        height = EstimateSpec.getSize(heightMeasureSpec);
        min = Math.min(width, height);
        imageSize = (int) (min * NUM_045);
        setRmsdbLevel(1);
        return false;
    }

    /**
     * 初始化
     */
    private void init() {
        backgroundPaint = new Paint();
        backgroundPaint.setColor(new Color(Color.getIntColor("#0080ff")));
        backgroundPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        wavePaint = new Paint();
        Color color = new Color(COLOR_INDICATOR_DEFAULT);
        wavePaint.setColor(color);
        wavePaint.setAntiAlias(true);
        wavePaint.setStyle(Paint.Style.STROKE_STYLE);
        wavePaint.setStrokeWidth(NUM_20);
        addDrawTask(this);
        setEstimateSizeListener(this);
    }

    /**
     * 1-30
     *
     * @param level 能量波大小
     */
    public void setRmsdbLevel(float level) {
        rmsdbLevel = level;
        invalidate();
    }

    /**
     * 设置颜色
     *
     * @param color 颜色值
     */
    public void setIndicatorColor(int color) {
        wavePaint.setColor(new Color(color));
        invalidate();
    }

    @Override
    public void invalidate() {
        super.invalidate();
        addDrawTask(this::onDraw);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        canvas.drawCircle((float) (width / (double) ER), (float) (height / (double) ER), getRadius(), backgroundPaint);
        PixelMap pixelMap = getPixelMap(ResourceTable.Media_microphone);
        rectSrc = new RectFloat((float) ((width - imageSize) / (double) ER),
                (float) ((height - imageSize) / (double) ER),
                (float) (width - ((width - imageSize) / (double) ER)),
                (float) (height - ((height - imageSize) / (double) ER)));
        pixelMapHolder = new PixelMapHolder(pixelMap);
        canvas.drawPixelMapHolderRect(pixelMapHolder, rectSrc, wavePaint);
    }

    /**
     * 通过能量画多大的圆
     *
     * @return 圆
     */
    private float getRadius() {
        double percent = (rmsdbLevel * Math.log(rmsdbLevel)) * NUM_001;
        percent = Math.min(Math.max(percent, 0f), YIF);
        percent = (double) NUM_055 + (double) NUM_045 * percent;
        return (float) (percent * ((float) min) / (double) ERF);
    }

    /**
     * 通过资源ID获取位图对象
     *
     * @param resId 资源id
     * @return PixelMap
     */
    private PixelMap getPixelMap(int resId) {
        InputStream drawableInputStream = null;
        PixelMap pixelMap = null;
        ImageSource imageSource = null;
        try {
            drawableInputStream = getResourceManager().getResource(resId);
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/png";
            imageSource = ImageSource.create(drawableInputStream, null);
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
            decodingOptions.desiredSize = new Size(0, 0);
            decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
            decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
            pixelMap = imageSource.createPixelmap(decodingOptions);
            return pixelMap;
        } catch (IOException ioException) {
            LogUtils.log(LogUtils.DEBUG, MICBUTTONTAG, ioException.getMessage());
        } catch (NotExistException notExistException) {
            LogUtils.log(LogUtils.DEBUG, MICBUTTONTAG, "notExistException");
        } finally {
            if (drawableInputStream != null) {
                try {
                    drawableInputStream.close();
                } catch (IOException e) {
                    LogUtils.log(LogUtils.DEBUG, MICBUTTONTAG, e.getMessage());
                }
            }
        }
        return pixelMap;
    }
}
